using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.IO;
using System.Xml;

namespace Common.Shared.Xml.Serialization {
  public class DictionarySerializer<K, V> {
    public struct SerializableKeyValuePair<TKey, TValue> {
      public TKey Key;
      public TValue Value;
      /// <summary>
      /// Initializes a new instance of the <see cref="SerializableKeyValuePair&lt;TKey, TValue&gt;"/> class.
      /// </summary>
      /// <param name="kvp">The KVP.</param>
      public SerializableKeyValuePair ( KeyValuePair<TKey, TValue> kvp ) {
        this.Key = kvp.Key;
        this.Value = kvp.Value;
      }
    }

    /// <summary>
    /// Serializes the specified dictionary.
    /// </summary>
    /// <param name="dictionary">The dictionary.</param>
    /// <param name="serializationStream">The serialization stream.</param>
    public void Serialize ( Dictionary<K, V> dictionary, XmlWriter serializationStream ) {
      XmlSerializer<List<SerializableKeyValuePair<K, V>>>.Serialize ( serializationStream, BuildItemList ( dictionary ) );
    }
    public void Serialize ( Dictionary<K, V> dictionary, TextWriter serializationStream ) {
      XmlSerializer<List<SerializableKeyValuePair<K, V>>>.Serialize ( serializationStream, BuildItemList ( dictionary ) );
    }
    public void Serialize ( Dictionary<K, V> dictionary, Stream serializationStream ) {
      XmlSerializer<List<SerializableKeyValuePair<K, V>>>.Serialize ( serializationStream, BuildItemList ( dictionary ) );
    }

    private List<SerializableKeyValuePair<K, V>> BuildItemList ( Dictionary<K, V> dictionary ) {
      List<SerializableKeyValuePair<K, V>> list = new List<SerializableKeyValuePair<K, V>> ( );
      foreach ( KeyValuePair<K, V> nonSerializableKVP in dictionary ) {
        list.Add ( new SerializableKeyValuePair<K, V> ( nonSerializableKVP ) );
      }

      return list;

    }


    public Dictionary<K, V> Deserialize ( XmlReader serializationStream ) {
      List<SerializableKeyValuePair<K, V>> dictionaryItems = XmlSerializer<List<SerializableKeyValuePair<K, V>>>.Deserialize ( serializationStream ) as List<SerializableKeyValuePair<K, V>>;
      return BuildDictionary ( dictionaryItems );
    }
    public Dictionary<K, V> Deserialize ( TextReader serializationStream ) {
      List<SerializableKeyValuePair<K, V>> dictionaryItems = XmlSerializer<List<SerializableKeyValuePair<K, V>>>.Deserialize ( serializationStream ) as List<SerializableKeyValuePair<K, V>>;
      return BuildDictionary ( dictionaryItems );
    }
    public Dictionary<K, V> Deserialize ( Stream serializationStream ) {
      List<SerializableKeyValuePair<K, V>> dictionaryItems = XmlSerializer<List<SerializableKeyValuePair<K, V>>>.Deserialize ( serializationStream ) as List<SerializableKeyValuePair<K, V>>;
      return BuildDictionary ( dictionaryItems );
    }

    private Dictionary<K, V> BuildDictionary ( List<SerializableKeyValuePair<K, V>> dictionaryItems ) {
      Dictionary<K, V> dictionary = new Dictionary<K, V> ( dictionaryItems.Count );
      foreach ( SerializableKeyValuePair<K, V> item in dictionaryItems ) {
        dictionary.Add ( item.Key, item.Value );
      }

      return dictionary;
    }
  }
}
